package com.navinfo.platform.trip.common.arithmetic;

import com.navinfo.platform.trip.common.arithmetic.data.CommonData;
import com.navinfo.platform.trip.common.arithmetic.data.OuterStatisticData;
import com.navinfo.platform.trip.common.arithmetic.enums.RangeSpeedEnum;
import com.navinfo.platform.trip.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.platform.trip.common.arithmetic.var.VarCommon;
import com.navinfo.platform.trip.common.arithmetic.var.VarRangeSpeed;
import com.navinfo.platform.trip.common.config.ConfigMap;
import com.navinfo.platform.trip.common.util.ArithmeticUtils;

import java.util.ArrayList;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Optional;

/**
 * 速度区间统计算法<br/>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 依赖{@link IdleParking}的怠速状态<br/>
 * 输出：统计
 * @author 沈东生
 */
public class RangeSpeed extends AbstractArithmetic<VarRangeSpeed> {
    /**
     * 有效车速时长比例阀值，根据这个统计最高最低有效车速 单位: 0-1 之间的double值
     */
    private static final double usefulPercent = ConfigMap.getDouble("SpeedRange_useful_percent_threshold");

    @Override
    public void calculate() {
        logger.debug("进入速度区间统计算法.[terminalId:{}]", terminalId);
        VarRangeSpeed var = getObj();
        CommonData commonData = getCommonData();
        int speed = commonData.getSpeedKmh();

        if (speed<0) {
            logger.error("速度区间统计算法,速度值不合法，不进行统计：speedKmh:{}", speed);
            return;
        }

        VarCommon varSpeed = null;
        VarRangeSpeed.UsefulSpeed usefulSpeed = var.getUsefulSpeed();
        if (RangeSpeedEnum.RANGE_10.getRange().contains(speed)) {
            varSpeed = var.getSpeed10();
            usefulSpeed.setUsefulSpeed10Min(speed);
            usefulSpeed.setUsefulSpeed10Max(speed);
        }else if(RangeSpeedEnum.RANGE_20.getRange().contains(speed)){
            varSpeed = var.getSpeed20();
            usefulSpeed.setUsefulSpeed20Min(speed);
            usefulSpeed.setUsefulSpeed20Max(speed);
        }else if(RangeSpeedEnum.RANGE_30.getRange().contains(speed)){
            varSpeed = var.getSpeed30();
            usefulSpeed.setUsefulSpeed30Min(speed);
            usefulSpeed.setUsefulSpeed30Max(speed);
        }else if(RangeSpeedEnum.RANGE_40.getRange().contains(speed)){
            varSpeed = var.getSpeed40();
            usefulSpeed.setUsefulSpeed40Min(speed);
            usefulSpeed.setUsefulSpeed40Max(speed);
        }else if(RangeSpeedEnum.RANGE_50.getRange().contains(speed)) {
            varSpeed = var.getSpeed50();
            usefulSpeed.setUsefulSpeed50Min(speed);
            usefulSpeed.setUsefulSpeed50Max(speed);
        }else if(RangeSpeedEnum.RANGE_60.getRange().contains(speed)) {
            varSpeed = var.getSpeed60();
            usefulSpeed.setUsefulSpeed60Min(speed);
            usefulSpeed.setUsefulSpeed60Max(speed);
        }else if(RangeSpeedEnum.RANGE_70.getRange().contains(speed)) {
            varSpeed = var.getSpeed70();
            usefulSpeed.setUsefulSpeed70Min(speed);
            usefulSpeed.setUsefulSpeed70Max(speed);
        }else if(RangeSpeedEnum.RANGE_80.getRange().contains(speed)) {
            varSpeed = var.getSpeed80();
            usefulSpeed.setUsefulSpeed80Min(speed);
            usefulSpeed.setUsefulSpeed80Max(speed);
        }else if(RangeSpeedEnum.RANGE_90.getRange().contains(speed)) {
            varSpeed = var.getSpeed90();
            usefulSpeed.setUsefulSpeed90Min(speed);
            usefulSpeed.setUsefulSpeed90Max(speed);
        }else if(RangeSpeedEnum.RANGE_100.getRange().contains(speed)) {
            varSpeed = var.getSpeed100();
            usefulSpeed.setUsefulSpeed100Min(speed);
            usefulSpeed.setUsefulSpeed100Max(speed);
        }else if(RangeSpeedEnum.RANGE_110.getRange().contains(speed)) {
            varSpeed = var.getSpeed110();
            usefulSpeed.setUsefulSpeed110Min(speed);
            usefulSpeed.setUsefulSpeed110Max(speed);
        }else if(RangeSpeedEnum.RANGE_120.getRange().contains(speed)) {
            varSpeed = var.getSpeed120();
            usefulSpeed.setUsefulSpeed120Min(speed);
            usefulSpeed.setUsefulSpeed120Max(speed);
        }else if(RangeSpeedEnum.RANGE_OVER_120.getRange().contains(speed)) {
            varSpeed = var.getSpeedOver120();
            usefulSpeed.setUsefulSpeedOver120Min(speed);
            usefulSpeed.setUsefulSpeedOver120Max(speed);
        }

        if(null != varSpeed){
            varSpeed.addMileage(commonData.getDffMileage());
            varSpeed.addFuel(commonData.getDffFuel());
            varSpeed.addDuration(commonData.getDffTime());
        }

        //非怠速状态下的最小速度
        if(commonData.isWork()) {
            var.setMinSpeed(var.getMinSpeed()==null ? speed : (var.getMinSpeed()>speed ? speed : var.getMinSpeed()));
            var.setMaxSpeed(var.getMaxSpeed()==null ? speed : (var.getMaxSpeed()<speed ? speed : var.getMaxSpeed()));
        }

        logger.debug("速度区间统计算法结束.[terminalId:{}]", terminalId);
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        VarRangeSpeed var = getObj();
        statisticDataOut.setSpeedRange01Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed10().getFuel()));
        statisticDataOut.setSpeedRange01Mileage(ArithmeticUtils.mileageMToM(var.getSpeed10().getMileage()));
        statisticDataOut.setSpeedRange01Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed10().getDuration()));

        statisticDataOut.setSpeedRange02Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed20().getFuel()));
        statisticDataOut.setSpeedRange02Mileage(ArithmeticUtils.mileageMToM(var.getSpeed20().getMileage()));
        statisticDataOut.setSpeedRange02Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed20().getDuration()));

        statisticDataOut.setSpeedRange03Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed30().getFuel()));
        statisticDataOut.setSpeedRange03Mileage(ArithmeticUtils.mileageMToM(var.getSpeed30().getMileage()));
        statisticDataOut.setSpeedRange03Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed30().getDuration()));

        statisticDataOut.setSpeedRange04Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed40().getFuel()));
        statisticDataOut.setSpeedRange04Mileage(ArithmeticUtils.mileageMToM(var.getSpeed40().getMileage()));
        statisticDataOut.setSpeedRange04Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed40().getDuration()));

        statisticDataOut.setSpeedRange05Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed50().getFuel()));
        statisticDataOut.setSpeedRange05Mileage(ArithmeticUtils.mileageMToM(var.getSpeed50().getMileage()));
        statisticDataOut.setSpeedRange05Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed50().getDuration()));

        statisticDataOut.setSpeedRange06Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed60().getFuel()));
        statisticDataOut.setSpeedRange06Mileage(ArithmeticUtils.mileageMToM(var.getSpeed60().getMileage()));
        statisticDataOut.setSpeedRange06Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed60().getDuration()));

        statisticDataOut.setSpeedRange07Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed70().getFuel()));
        statisticDataOut.setSpeedRange07Mileage(ArithmeticUtils.mileageMToM(var.getSpeed70().getMileage()));
        statisticDataOut.setSpeedRange07Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed70().getDuration()));

        statisticDataOut.setSpeedRange08Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed80().getFuel()));
        statisticDataOut.setSpeedRange08Mileage(ArithmeticUtils.mileageMToM(var.getSpeed80().getMileage()));
        statisticDataOut.setSpeedRange08Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed80().getDuration()));

        statisticDataOut.setSpeedRange09Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed90().getFuel()));
        statisticDataOut.setSpeedRange09Mileage(ArithmeticUtils.mileageMToM(var.getSpeed90().getMileage()));
        statisticDataOut.setSpeedRange09Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed90().getDuration()));

        statisticDataOut.setSpeedRange10Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed100().getFuel()));
        statisticDataOut.setSpeedRange10Mileage(ArithmeticUtils.mileageMToM(var.getSpeed100().getMileage()));
        statisticDataOut.setSpeedRange10Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed100().getDuration()));

        statisticDataOut.setSpeedRange11Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed110().getFuel()));
        statisticDataOut.setSpeedRange11Mileage(ArithmeticUtils.mileageMToM(var.getSpeed110().getMileage()));
        statisticDataOut.setSpeedRange11Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed110().getDuration()));

        statisticDataOut.setSpeedRange12Fuel(ArithmeticUtils.fuelMlToMl(var.getSpeed120().getFuel()));
        statisticDataOut.setSpeedRange12Mileage(ArithmeticUtils.mileageMToM(var.getSpeed120().getMileage()));
        statisticDataOut.setSpeedRange12Duration(ArithmeticUtils.timeMsToSecond(var.getSpeed120().getDuration()));

        statisticDataOut.setExceedSpeedRangeFuel(ArithmeticUtils.fuelMlToMl(var.getSpeedOver120().getFuel()));
        statisticDataOut.setExceedSpeedRangeMileage(ArithmeticUtils.mileageMToM(var.getSpeedOver120().getMileage()));
        statisticDataOut.setExceedSpeedRangeDuration(ArithmeticUtils.timeMsToSecond(var.getSpeedOver120().getDuration()));

        //最大最小速度
        statisticDataOut.setMinSpeed(var.getMinSpeed());
        statisticDataOut.setMaxSpeed(var.getMaxSpeed());

        //求最大最小有效速度
        VarRangeSpeed.UsefulSpeed usefulSpeed = var.getUsefulSpeed();
        double workDuration = getCommonData().getIntegralDuration();
        if (workDuration > 0) {
            //有效速度列表
            List<Integer> usefulSpeedList = new ArrayList<>();

            if (var.getSpeed10().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed10Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed10Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed20().getDuration()/workDuration  > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed20Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed20Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed30().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed30Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed30Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed40().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed40Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed40Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed50().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed50Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed50Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed60().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed60Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed60Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed70().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed70Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed70Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed80().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed80Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed80Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed90().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed90Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed90Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed100().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed100Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed100Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed110().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed110Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed110Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeed120().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeed120Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeed120Max()).ifPresent(usefulSpeedList::add);
            }
            if (var.getSpeedOver120().getDuration()/workDuration > usefulPercent) {
                Optional.ofNullable(usefulSpeed.getSpeedOver120Min()).ifPresent(usefulSpeedList::add);
                Optional.ofNullable(usefulSpeed.getSpeedOver120Max()).ifPresent(usefulSpeedList::add);
            }

            //设置有效的最大最小速度
            if (usefulSpeedList.size()>0) {
                IntSummaryStatistics intSummaryStatistics = usefulSpeedList.stream().mapToInt(Integer::intValue).summaryStatistics();
                statisticDataOut.setMinUsefulSpeed(intSummaryStatistics.getMin());
                statisticDataOut.setMaxUsefulSpeed(intSummaryStatistics.getMax());
            }
        } else {
            logger.error("engineWorkDuration<=0");
        }
    }
}
